package nfa;

import fa.FARule;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.assertEquals;

/**
 * @author haoly
 * @title NFARulebookTest
 * @date 2025/4/16 14:27
 * @description NFARulebookTest
 */
public class NFARulebookTest {
    @Test
    void testNextStates() {
        List<FARule<Integer>> rules = Arrays.asList(
                new FARule<>(1, 'a', 1),
                new FARule<>(1, 'b', 1),
                new FARule<>(1, 'b', 2),
                new FARule<>(2, 'a', 3),
                new FARule<>(2, 'b', 3),
                new FARule<>(3, 'a', 4),
                new FARule<>(3, 'b', 4)
        );
        NFARulebook<Integer> rulebook = new NFARulebook<>(rules);

        assertEquals(Set.of(1,2), rulebook.nextStates(Set.of(1), 'b'));

        assertEquals(Set.of(1,3), rulebook.nextStates(Set.of(1,2), 'a'));

        assertEquals(Set.of(1,2,4), rulebook.nextStates(Set.of(1,3), 'b'));

    }

    @Test
    void testNextStates2() {
        List<FARule<Integer>> rules = Arrays.asList(
                new FARule<>(1, null, 2),
                new FARule<>(1, null, 4),
                new FARule<>(2, 'a', 3),
                new FARule<>(3, 'a', 2),
                new FARule<>(4, 'a', 5),
                new FARule<>(5, 'a', 6),
                new FARule<>(6, 'a', 4)
        );
        NFARulebook<Integer> rulebook = new NFARulebook<>(rules);

        assertEquals(Set.of(2,4), rulebook.nextStates(Set.of(1), null));
    }
    @Test
    void testFreeMoves() {
        List<FARule<Integer>> rules = Arrays.asList(
                new FARule<>(1, null, 2),
                new FARule<>(1, null, 4),
                new FARule<>(2, 'a', 3),
                new FARule<>(3, 'a', 2),
                new FARule<>(4, 'a', 5),
                new FARule<>(5, 'a', 6),
                new FARule<>(6, 'a', 4)
        );
        NFARulebook<Integer> rulebook = new NFARulebook<>(rules);

        assertEquals(Set.of(1,2,4), rulebook.followFreeMoves(Set.of(1)));
    }

    @Test
    void testAlphabet() {
        List<FARule<Integer>> rules = Arrays.asList(
                new FARule<>(1, 'a', 1),
                new FARule<>(1, 'a', 2),
                new FARule<>(1, null, 2),
                new FARule<>(2, 'b', 3),
                new FARule<>(3, 'b', 1),
                new FARule<>(3, null, 2)
        );

        NFARulebook<Integer> rulebook = new NFARulebook<>(rules);
        assertEquals(Set.of('a','b'), rulebook.alphabet());
    }

}
